home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / SRC1229A.ARJ / AX25.C < prev    next >
C/C++ Source or Header  |  1991-03-10  |  13KB  |  458 lines

  1. /* Low level AX.25 code:
  2.  *  incoming frame processing (including digipeating)
  3.  *  IP encapsulation
  4.  *  digipeater routing
  5.  *
  6.  * Copyright 1991 Phil Karn, KA9Q
  7.  */
  8. #include <stdio.h>
  9. #include "global.h"
  10. #include "mbuf.h"
  11. #include "iface.h"
  12. #include "arp.h"
  13. #include "slip.h"
  14. #include "ax25.h"
  15. #include "lapb.h"
  16. #include "netrom.h"
  17. #include "ip.h"
  18. #include "devparam.h"
  19. #include <ctype.h>
  20.  
  21. static int axsend __ARGS((struct iface *iface,char *dest,char *source,
  22.     int cmdrsp,int ctl,struct mbuf *data));
  23.  
  24. /* List of AX.25 multicast addresses in network format (shifted ascii).
  25.  * Only the first entry is used for transmission, but an incoming
  26.  * packet with any one of these destination addresses is recognized
  27.  * as a multicast.
  28.  */
  29. char Ax25multi[][AXALEN] = {
  30.     'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1,    /* QST */
  31.     'M'<<1, 'A'<<1, 'I'<<1, 'L'<<1, ' '<<1, ' '<<1, '0'<<1,    /* MAIL */
  32.     'N'<<1, 'O'<<1, 'D'<<1, 'E'<<1, 'S'<<1, ' '<<1, '0'<<1,    /* NODES */
  33.     'I'<<1, 'D'<<1, ' '<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1,    /* ID */
  34.     'O'<<1, 'P'<<1, 'E'<<1, 'N'<<1, ' '<<1, ' '<<1, '0'<<1,    /* OPEN */
  35.     'C'<<1, 'Q'<<1, ' '<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1,    /* CQ */
  36.     'B'<<1, 'E'<<1, 'A'<<1, 'C'<<1, 'O'<<1, 'N'<<1, '0'<<1,    /* BEACON */
  37.     'R'<<1, 'M'<<1, 'N'<<1, 'C'<<1, ' '<<1, ' '<<1, '0'<<1,    /* RMNC */
  38.     'A'<<1, 'L'<<1, 'L'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1,    /* ALL */
  39.     '\0',
  40. };
  41. char Mycall[AXALEN];
  42. struct ax_route *Ax_routes;    /* Routing table header */
  43. int Digipeat = 1;    /* Controls digipeating */
  44.  
  45. /* Send IP datagrams across an AX.25 link */
  46. int
  47. ax_send(bp,iface,gateway,prec,del,tput,rel)
  48. struct mbuf *bp;
  49. struct iface *iface;
  50. int32 gateway;
  51. int prec;
  52. int del;
  53. int tput;
  54. int rel;
  55. {
  56.     char *hw_addr;
  57.     struct ax25_cb *axp;
  58.     struct mbuf *tbp;
  59.  
  60.     if((hw_addr = res_arp(iface,ARP_AX25,gateway,bp)) == NULLCHAR)
  61.         return 0;    /* Wait for address resolution */
  62.  
  63.     /* UI frames are used for any one of the following three conditions:
  64.      * 1. The "low delay" bit is set in the type-of-service field.
  65.      * 2. The "reliability" TOS bit is NOT set and the interface is in
  66.      *    datagram mode.
  67.      * 3. The destination is the broadcast address (this is helpful
  68.      *    when broadcasting on an interface that's in connected mode).
  69.      */
  70.     if(del || (!rel && (iface->flags == DATAGRAM_MODE))
  71.      || addreq(hw_addr,Ax25multi[0])){
  72.         /* Use UI frame */
  73.         return (*iface->output)(iface,hw_addr,iface->hwaddr,PID_IP,bp);
  74.     }
  75.     /* Reliability is needed; use I-frames in AX.25 connection */
  76.     if((axp = find_ax25(hw_addr)) == NULLAX25){
  77.         /* Open a new connection */
  78.         axp = open_ax25(iface,iface->hwaddr,hw_addr,
  79.          AX_ACTIVE,Axwindow,s_arcall,s_atcall,s_ascall,-1);
  80.         if(axp == NULLAX25){
  81.             free_p(bp);
  82.             return -1;
  83.         }
  84.     }
  85.     if(axp->state == LAPB_DISCONNECTED){
  86.         est_link(axp);
  87.         lapbstate(axp,LAPB_SETUP);
  88.     }
  89.     /* Insert the PID */
  90.     if((tbp = pushdown(bp,1)) == NULLBUF){
  91.         free_p(bp);
  92.         return -1;
  93.     }
  94.     bp = tbp;
  95.     bp->data[0] = PID_IP;
  96.     if((tbp = segmenter(bp,axp->paclen)) == NULLBUF){
  97.         free_p(bp);
  98.         return -1;
  99.     }
  100.     return send_ax25(axp,tbp,-1);
  101. }
  102. /* Add header and send connectionless (UI) AX.25 packet.
  103.  * Note that the calling order here must match enet_output
  104.  * since ARP also uses it.
  105.  */
  106. int
  107. ax_output(iface,dest,source,pid,data)
  108. struct iface *iface;    /* Interface to use; overrides routing table */
  109. char *dest;        /* Destination AX.25 address (7 bytes, shifted) */
  110. char *source;        /* Source AX.25 address (7 bytes, shifted) */
  111. int16 pid;        /* Protocol ID */
  112. struct mbuf *data;    /* Data field (follows PID) */
  113. {
  114.     struct mbuf *bp;
  115.  
  116.     /* Prepend pid to data */
  117.     bp = pushdown(data,1);
  118.     if(bp == NULLBUF){
  119.         free_p(data);
  120.         return -1;
  121.     }
  122.     bp->data[0] = (char)pid;
  123.     return axsend(iface,dest,source,LAPB_COMMAND,UI,bp);
  124. }
  125. /* Common subroutine for sendframe() and ax_output() */
  126. static int
  127. axsend(iface,dest,source,cmdrsp,ctl,data)
  128. struct iface *iface;    /* Interface to use; overrides routing table */
  129. char *dest;        /* Destination AX.25 address (7 bytes, shifted) */
  130. char *source;        /* Source AX.25 address (7 bytes, shifted) */
  131. int cmdrsp;        /* Command/response indication */
  132. int ctl;        /* Control field */
  133. struct mbuf *data;    /* Data field (includes PID) */
  134. {
  135.     struct mbuf *cbp;
  136.     struct ax25 addr;
  137.     struct ax_route *axr;
  138.     char *idest;
  139.     int rval;
  140.  
  141.     /* If the source addr is unspecified, use the interface address */
  142.     if(source[0] == '\0')
  143.         source = iface->hwaddr;
  144.  
  145.     /* If there's a digipeater route, get it */
  146.     axr = ax_lookup(dest);
  147.  
  148.     memcpy(addr.dest,dest,AXALEN);
  149.     memcpy(addr.source,source,AXALEN);
  150.     addr.cmdrsp = cmdrsp;
  151.  
  152.     if(axr != NULLAXR){
  153.         memcpy(addr.digis,axr->digis,axr->ndigis*AXALEN);
  154.         addr.ndigis = axr->ndigis;
  155.         idest = addr.digis[0];
  156.     } else {
  157.         addr.ndigis = 0;
  158.         idest = dest;
  159.     }
  160.     addr.nextdigi = 0;
  161.  
  162.     /* Allocate mbuf for control field, and fill in */
  163.     if((cbp = pushdown(data,1)) == NULLBUF){
  164.         free_p(data);
  165.         return -1;
  166.     }
  167.     cbp->data[0] = ctl;
  168.  
  169.     if((data = htonax25(&addr,cbp)) == NULLBUF){
  170.         free_p(cbp);    /* Also frees data */
  171.         return -1;
  172.     }
  173.     /* This shouldn't be necessary because redirection has already been
  174.      * done at the IP router layer, but just to be safe...
  175.      */
  176.     if(iface->forw != NULLIF){
  177.         logsrc(iface->forw,iface->forw->hwaddr);
  178.         logdest(iface->forw,idest);
  179.         rval = (*iface->forw->raw)(iface->forw,data);
  180.     } else {
  181.         logsrc(iface,iface->hwaddr);
  182.         logdest(iface,idest);
  183.         rval = (*iface->raw)(iface,data);
  184.     }
  185.     return rval;
  186. }
  187. /* Process incoming AX.25 packets.
  188.  * After optional tracing, the address field is examined. If it is
  189.  * directed to us as a digipeater, repeat it.  If it is addressed to
  190.  * us or to QST-0, kick it upstairs depending on the protocol ID.
  191.  */
  192. void
  193. ax_recv(iface,bp)
  194. struct iface *iface;
  195. struct mbuf *bp;
  196. {
  197.     struct mbuf *hbp;
  198.     char control;
  199.     struct ax25 hdr;
  200.     struct ax25_cb *axp;
  201.     struct ax_route *axr;
  202.     char (*mpp)[AXALEN];
  203.     int mcast;
  204.     char *isrc,*idest;    /* "immediate" source and destination */
  205.  
  206.     /* Pull header off packet and convert to host structure */
  207.     if(ntohax25(&hdr,&bp) < 0){
  208.         /* Something wrong with the header */
  209.         free_p(bp);
  210.         return;
  211.     }
  212.     /* If there were digis in this packet and at least one has
  213.      * been passed, then the last passed digi is the immediate source.
  214.      * Otherwise it is the original source.
  215.      */
  216.     if(hdr.ndigis != 0 && hdr.nextdigi != 0)
  217.         isrc = hdr.digis[hdr.nextdigi-1];
  218.     else
  219.         isrc = hdr.source;
  220.  
  221.     /* If there are digis in this packet and not all have been passed,
  222.      * then the immediate destination is the next digi. Otherwise it
  223.      * is the final destination.
  224.      */
  225.     if(hdr.ndigis != 0 && hdr.nextdigi != hdr.ndigis)
  226.         idest = hdr.digis[hdr.nextdigi];
  227.     else
  228.         idest = hdr.dest;
  229.  
  230.     /* Don't log our own packets if we overhear them, as they're
  231.      * already logged by axsend() and by the digipeater code.
  232.      */
  233.     if(!addreq(isrc,iface->hwaddr)){
  234.         logsrc(iface,isrc);
  235.         logdest(iface,idest);
  236.     }
  237.     /* Examine immediate destination for a multicast address */
  238.     mcast = 0;
  239.     for(mpp = Ax25multi;(*mpp)[0] != '\0';mpp++){
  240.         if(addreq(idest,*mpp)){
  241.             mcast = 1;
  242.             break;
  243.         }
  244.     }
  245.     if(!mcast && !addreq(idest,iface->hwaddr)){
  246.         /* Not a broadcast, and not addressed to us. Inhibit
  247.          * transmitter to avoid colliding with addressed station's
  248.          * response, and discard packet.
  249.          */
  250.         if(iface->ioctl != NULL)
  251.             (*iface->ioctl)(iface,PARAM_MUTE,1,-1);
  252.         free_p(bp);
  253.         return;
  254.     }
  255.     if(!mcast && iface->ioctl != NULL){
  256.         /* Packet was sent to us; abort transmit inhibit */
  257.         (*iface->ioctl)(iface,PARAM_MUTE,1,0);
  258.     }
  259.     /* At this point, packet is either addressed to us, or is
  260.      * a multicast.
  261.      */
  262.     if(hdr.nextdigi < hdr.ndigis){
  263.         /* Packet requests digipeating. See if we can repeat it. */
  264.         if(Digipeat && !mcast){
  265.             /* Yes, kick it back out. htonax25 will set the
  266.              * repeated bit.
  267.              */
  268.             hdr.nextdigi++;
  269.             if((hbp = htonax25(&hdr,bp)) != NULLBUF){
  270.                 if(iface->forw != NULLIF){
  271.                     logsrc(iface->forw,iface->forw->hwaddr);
  272.                     logdest(iface->forw,hdr.digis[hdr.nextdigi]);
  273.                     (*iface->forw->raw)(iface->forw,hbp);
  274.                 } else {
  275.                     logsrc(iface,iface->hwaddr);
  276.                     logdest(iface,hdr.digis[hdr.nextdigi]);
  277.                     (*iface->raw)(iface,hbp);
  278.                 }
  279.                 bp = NULLBUF;
  280.             }
  281.         }
  282.         free_p(bp);    /* Dispose if not forwarded */
  283.         return;
  284.     }
  285.     /* If we reach this point, then the packet has passed all digis,
  286.      * and is either addressed to us or is a multicast.
  287.      */
  288.     if(bp == NULLBUF)
  289.         return;        /* Nothing left */
  290.  
  291.     /* If there's no locally-set entry in the routing table and
  292.      * this packet has digipeaters, create or update it. Leave
  293.      * local routes alone.
  294.      */
  295.     if(((axr = ax_lookup(hdr.source)) == NULLAXR || axr->type == AX_AUTO)
  296.      && hdr.ndigis > 0){
  297.         char digis[MAXDIGIS][AXALEN];
  298.         int i,j;
  299.  
  300.         /* Construct reverse digipeater path */
  301.         for(i=hdr.ndigis-1,j=0;i >= 0;i--,j++){
  302.             memcpy(digis[j],hdr.digis[i],AXALEN);
  303.             digis[j][ALEN] &= ~(E|REPEATED);
  304.         }
  305.         ax_add(hdr.source,AX_AUTO,digis,hdr.ndigis);
  306.     }
  307.     /* Sneak a peek at the control field. This kludge is necessary because
  308.      * AX.25 lacks a proper protocol ID field between the address and LAPB
  309.      * sublayers; a control value of UI indicates that LAPB is to be
  310.      * bypassed.
  311.      */
  312.     control = *bp->data & ~PF;
  313.  
  314.     if(uchar(control) == UI){
  315.         int pid;
  316.         struct axlink *ipp;
  317.  
  318.         (void) PULLCHAR(&bp);
  319.         if((pid = PULLCHAR(&bp)) == -1)
  320.             return;        /* No PID */
  321.         /* Find network level protocol and hand it off */
  322.         for(ipp = Axlink;ipp->funct != NULL;ipp++){
  323.             if(ipp->pid == pid)
  324.                 break;
  325.         }
  326.         if(ipp->funct != NULL)
  327.             (*ipp->funct)(iface,NULLAX25,hdr.source,hdr.dest,bp,mcast);
  328.         else
  329.             free_p(bp);
  330.         return;
  331.     }
  332.     /* Everything from here down is connected-mode LAPB, so ignore
  333.      * multicasts
  334.      */
  335.     if(mcast){
  336.         free_p(bp);
  337.         return;
  338.     }
  339.     /* Find the source address in hash table */
  340.     if((axp = find_ax25(hdr.source)) == NULLAX25){
  341.         /* Create a new ax25 entry for this guy,
  342.          * insert into hash table keyed on his address,
  343.          * and initialize table entries
  344.          */
  345.         if((axp = cr_ax25(hdr.source)) == NULLAX25){
  346.             free_p(bp);
  347.             return;
  348.         }
  349.         /* Swap source and destination */
  350.         memcpy(axp->remote,hdr.source,AXALEN);
  351.         memcpy(axp->local,hdr.dest,AXALEN);
  352.         axp->iface = iface;
  353.     }
  354.     if(hdr.cmdrsp == LAPB_UNKNOWN)
  355.         axp->proto = V1;    /* Old protocol in use */
  356.  
  357.     lapb_input(axp,hdr.cmdrsp,bp);
  358. }
  359. /* General purpose AX.25 frame output */
  360. int
  361. sendframe(axp,cmdrsp,ctl,data)
  362. struct ax25_cb *axp;
  363. int cmdrsp;
  364. int ctl;
  365. struct mbuf *data;
  366. {
  367.     return axsend(axp->iface,axp->remote,axp->local,cmdrsp,ctl,data);
  368. }
  369. /* Find a route for an AX.25 address */
  370. struct ax_route *
  371. ax_lookup(target)
  372. char *target;
  373. {
  374.     register struct ax_route *axr;
  375.     struct ax_route *axlast = NULLAXR;
  376.  
  377.     for(axr = Ax_routes; axr != NULLAXR; axlast=axr,axr = axr->next){
  378.         if(addreq(axr->target,target)){
  379.             if(axr != Ax_routes){
  380.                 /* Move entry to top of list to speed
  381.                  * future searches
  382.                  */
  383.                 axlast->next = axr->next;
  384.                 axr->next = Ax_routes;
  385.                 Ax_routes = axr;
  386.  
  387.             }
  388.             return axr;
  389.         }
  390.     }
  391.     return axr;
  392. }
  393. /* Add an entry to the AX.25 routing table */
  394. struct ax_route *
  395. ax_add(target,type,digis,ndigis)
  396. char *target;
  397. int type;
  398. char digis[][AXALEN];
  399. int ndigis;
  400. {
  401.     register struct ax_route *axr;
  402.  
  403.     if(ndigis < 0 || ndigis > MAXDIGIS)
  404.         return NULLAXR;
  405.  
  406.     if((axr = ax_lookup(target)) == NULLAXR){
  407.         axr = (struct ax_route *)callocw(1,sizeof(struct ax_route));
  408.         axr->next = Ax_routes;
  409.         Ax_routes = axr;
  410.         memcpy(axr->target,target,AXALEN);
  411.         axr->ndigis = ndigis;
  412.     }
  413.     axr->type = type;
  414.     if(axr->ndigis != ndigis)
  415.         axr->ndigis = ndigis;
  416.  
  417.     memcpy(axr->digis,digis[0],ndigis*AXALEN);
  418.     return axr;
  419. }
  420. int
  421. ax_drop(target)
  422. char *target;
  423. {
  424.     register struct ax_route *axr;
  425.     struct ax_route *axlast = NULLAXR;
  426.  
  427.     for(axr = Ax_routes;axr != NULLAXR;axlast=axr,axr=axr->next)
  428.         if(memcmp(axr->target,target,AXALEN) == 0)
  429.             break;
  430.     if(axr == NULLAXR)
  431.         return -1;    /* Not in table! */
  432.     if(axlast != NULLAXR)
  433.         axlast->next = axr->next;
  434.     else
  435.         Ax_routes = axr->next;
  436.     
  437.     free((char *)axr);
  438.     return 0;
  439. }
  440. /* Handle ordinary incoming data (no network protocol) */
  441. void
  442. axnl3(iface,axp,src,dest,bp,mcast)
  443. struct iface *iface;
  444. struct ax25_cb *axp;
  445. char *src;
  446. char *dest;
  447. struct mbuf *bp;
  448. int mcast;
  449. {
  450.     if(axp == NULLAX25){
  451.         beac_input(iface,src,bp);
  452.     } else {
  453.         append(&axp->rxq,bp);
  454.         if(axp->r_upcall != NULLVFP)
  455.             (*axp->r_upcall)(axp,len_p(axp->rxq));
  456.     }
  457. }
  458.